package com.example.demo.com.java8.lambda;

import org.junit.Test;

import java.util.Comparator;
import java.util.function.Consumer;

/**
 * 一、Lambda 表达式基础语法，Java8中引入了一个新的操作特性，"->"，叫做lambda操作符
 * 左侧：lambda表达式的参数列表
 * 右侧：lambda 表达式所需的功能，lambda体
 *
 * lambda 表达式需要函数式接口支持，
 * 函数式接口：只有一个抽象方法的接口
 * 左侧参数就是抽象方法的参数
 * 右侧就是该接口的具体实现
 *
 * lambda表达式其实就是一个语法糖，底层其实还是该接口的具体实现（包裹着类似于参数的糖衣，揭开糖衣里面是接口实现）
 *
 * 语法格式一：无参数，无返回值
 *      ()-> {System.out.println("Hello world！")};
 *
 * 语法格式二：有参数，无无返回值
 *      (x)-> System.out.println(x);
 *      只有一个参数，小括号可以不写
 *
 * 语法格式三：有两个以上参数，有返回值
 *      (x,y)-> {
 *              System.out.println(x);
 *              return Integer.compare(x, y);
 *         }
 *      多条语句用大括号括起来
 * 语法格式四：有两个以上参数，y有返回值
 *      (x,y)-> Integer.compare(x, y);
 *
 *      如果只有一条语句，有返回值，大括号和return都可以不写
 * 语法格式五：Lambda表达式的参数类型可以不写，因为jvm编译器可以根据上下文推断出来数据类型
 *
 *
 * 左右遇一括号省
 * 左侧推断类型省
 * 能省则省
 *
 * @author chengfei5
 * @date 2018/8/20
 */
public class LambdaTest2 {
    @Test
    public void test1(){
        //jdk1.7以前必须是定义final，jdk1.8以后不用定义，默认已经定义为final
        int num = 1;
        Runnable r = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello world！"+num);
            }
        };
        r.run();
        System.out.println("-----------------");
        //通过lambda 表达式
        Runnable r1 = ()-> System.out.println("Hello lambda"+num);
        r1.run();
    }

    @Test
    public void test2(){
        Consumer<String> consumer = (x)-> System.out.println(x);
        consumer.accept("hello lambda!");
    }
    @Test
    public void test3(){
        Consumer<String> consumer = x-> System.out.println(x);
        consumer.accept("hello lambda!");
    }

    /**
     * 1. 默认方法与静态方法并不影响函数式接口的契约，可以任意使用，即
 　　 　　　函数式接口中可以有静态方法，一个或者多个静态方法不会影响SAM接口成为函数式接口，并且静态方法可以提供方法实现
 　　　　　　可以由 default 修饰的默认方法方法，这个关键字是Java8中新增的，为的目的就是使得某一些接口，原则上只有一个方法被实现，但是由于历史原因，不得不加入一些方法来兼容整个JDK中的API，所以就需要使用default关键字来定义这样的方法
 　　　　2. 可以有 Object 中覆盖的方法，也就是 equals，toString，hashcode等方法。
     */
    @Test
    public void test4(){
        Comparator<Integer> comparable = (x, y) -> {
            System.out.println("函数式接口");
            return Integer.compare(x, y);
        };
        System.out.println(comparable.compare(3,5));
    }

    @Test
    public void test5(){
        //可以修改为方法引用
        Comparator<Integer> comparable = (x, y) -> Integer.compare(x, y);
//        Comparator<Integer> comparable = Integer::compare;

        System.out.println(comparable.compare(3,5));
    }

    @Test
    public void test6(){
        Comparator<Integer> comparable = (Integer x, Integer y) -> Integer.compare(x, y);
        System.out.println(comparable.compare(3,5));
    }

    @Test
    public void test7(){
        //平方操作
        System.out.println(operation(100,x->x*x));
        //加法操作
        System.out.println(operation(200,y->y+200));
    }

    @Test
    public void test8(){
        //小写变大写
        System.out.println(operation("asdfasegsaegse",str -> str.toUpperCase()));
        //去空格
        System.out.println(operation("\t\t\tasdfasegsaegse\t\t\t",str -> str.trim()));
        //截取
        System.out.println(operation("asdfasegsaegse",str -> str.substring(2,5)));

    }

    public Integer operation(Integer num,MyFun mf){
        return mf.getValue(num);
    }

    public String operation(String Str,StringFun stringFun){
        return stringFun.getValue(Str);
    }
}
